#ifndef LABEL_FILE_H
#define LABEL_FILE_H

#include <string>
#include <vector>
#include <map>
#include <stdexcept>
#include <opencv2/opencv.hpp>
#include <nlohmann/json.hpp>


// **LabelFileError Exception Class**
class LabelFileError : public std::runtime_error {
public:
    explicit LabelFileError(const std::string& message);
};

// **Shape Class Definition**
class Shape {
public:
    std::string label;
    std::vector<std::vector<float>> points; // Vector of (x, y) points
    int group_id = -1;
    std::string shape_type = "polygon";
    std::map<std::string, bool> flags;
    std::string description;
    cv::Mat mask; // Mask image as cv::Mat
    nlohmann::json other_data; // Additional data

    // Constructor
    Shape() = default;
};

// **LabelFile Class Definition**
class LabelFile {
public:
    const static std::string suffix;

    // Member variables
    std::vector<Shape> shapes;
    std::string imagePath;
    std::string imageData; // Base64-encoded image data
    std::map<std::string, bool> flags;
    nlohmann::json otherData;
    std::string filename;

    // Constructor
    explicit LabelFile(const std::string& filename = "");

    // Static methods
    static std::string load_image_file(const std::string& filename);

    // Methods
    void load(const std::string& filename);
    void save(const std::string& filename,
              const std::vector<Shape>& shapes,
              const std::string& imagePath,
              int imageHeight,
              int imageWidth,
              const std::string& imageData = "",
              const nlohmann::json& otherData = {},
              const std::map<std::string, bool>& flags = {});

    static bool is_label_file(const std::string& filename);

private:
    void _check_image_height_and_width(const std::string& imageData, int& imageHeight, int& imageWidth);
};

const std::string LabelFile::suffix = ".json";

#endif // LABEL_FILE_H
